package com.xiaobai.login.service;

import com.xiaobai.common.base.CommonRuntimeException;
import com.xiaobai.common.base.ErrorCode;
import com.xiaobai.config.JwtProperties;
import com.xiaobai.login.dao.ILoginDao;
import com.xiaobai.login.entity.LoginUser;
import com.xiaobai.login.request.*;
import com.xiaobai.login.response.LoginRes;
import com.xiaobai.login.response.UserInfoRes;
import com.xiaobai.upload.UploadController;
import com.xiaobai.util.FileUtil;
import com.xiaobai.util.LoginUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

/**
 * 用户登陆Service
 *
 * @author bail
 * @date 2018/12/30.15:39
 */
@Service
@Slf4j
public class LoginService {
    @Autowired
    private ILoginDao loginDao;

    @Autowired
    private JwtProperties jwtProperties;

    /**
     * 登陆逻辑
     *
     * @param userReq 输入的用户名与密码
     * @return token
     */
    public LoginRes login(LoginUserReq userReq) {
        UserQueryOneReq userQueryOneReq = new UserQueryOneReq();
        userQueryOneReq.setUserPhone(userReq.getAccount());
        LoginUser user = loginDao.queryOneUser(userQueryOneReq);
        if (user == null) {
            // 用户不存在,即用户名错误
            throw new CommonRuntimeException(ErrorCode.WRONG_LOGIN_ACCOUNT);
        } else {
            // 验证输入的密码是否正确
            String secPassword = toHexString(
                    md5Hex(user.getUserId() + toHexString(md5Hex(userReq.getPassword())) + user.getUserSalt())
            );
            if (!user.getUserPassword().equals(secPassword)) {
                throw new CommonRuntimeException(ErrorCode.WRONG_LOGIN_PASSWORD);
            }
        }
        return LoginUtil.getLoginResponse(user, jwtProperties.getSecretKey());
    }

    /**
     * 查询登录人基本信息
     * @return 用户基本信息
     */
    public UserInfoRes loginQuery() {
        UserQueryOneReq userQueryOneReq = new UserQueryOneReq();
        userQueryOneReq.setUserId(LoginUtil.getUserId());
        return loginDao.loginQuery(userQueryOneReq);
    }

    /**
     * 删除用户头像
     */
    public void deleteUserPhoto(UserPhotoDelReq userPhotoDelReq) {
        // 1.查询待删除的图片是否已经入库
        UserQueryOneReq userQueryOneReq = new UserQueryOneReq();
        userQueryOneReq.setUserPhoto(userPhotoDelReq.getUserPhoto());
        LoginUser userRes = loginDao.queryOneUser(userQueryOneReq);

        if (userRes == null) {
            // 2.未入库,则可以直接删除
            // ☆☆☆一定要注意:只能删单个文件,若用户传入的是一个文件夹是十分危险的操作☆☆☆
            FileUtil.delFile(UploadController.DIR_PATH_PREFIX + userPhotoDelReq.getUserPhoto());
        } else {
            // 3.已入库,则校验该图片是否隶属于当前登录人
            Long userId = LoginUtil.getUserId();
            if (userRes.getUserId().equals(userId)) {
                // 4.1.隶属于登录人,则可以删除图片
                FileUtil.delFile(UploadController.DIR_PATH_PREFIX + userPhotoDelReq.getUserPhoto());

                // 4.2.清空用户头像字段
                UserUpdateReq userUpdateReq = new UserUpdateReq();
                userUpdateReq.setUserId(userId);
                userUpdateReq.setUserPhoto(null);
                loginDao.updateUserPhoto(userUpdateReq);
            } else {
                throw new CommonRuntimeException(ErrorCode.COMMON_FAIL, "您没有权限删除该图片");
            }
        }
    }

    /**
     * 修改用户基本信息
     * @return 用户基本信息
     */
    public void updateUserInfo(UserUpdateReq userUpdateReq) {
        loginDao.updateUserInfo(userUpdateReq);
    }

    /**
     * 修改用户登录密码
     * @return 用户密码
     */
    public void updatePassword(UserPasswordUpdateReq userPasswordUpdateReq) {
        UserQueryOneReq userQueryOneReq = new UserQueryOneReq();
        userQueryOneReq.setUserId(userPasswordUpdateReq.getUserId());
        LoginUser user = loginDao.queryOneUser(userQueryOneReq);
        // 根据盐值生成新密码
        userPasswordUpdateReq.setUserPassword(
                toHexString(md5Hex(user.getUserId() +
                        toHexString(md5Hex(userPasswordUpdateReq.getUserPassword())) +
                        user.getUserSalt()))
        );
        loginDao.updatePassword(userPasswordUpdateReq);
    }

    /**
     * hex加密
     *
     * @param b 待加密字节数组
     * @return 加密后的字符串
     */
    private static String toHexString(byte[] b) {
        StringBuilder sb = new StringBuilder();

        for (int i = 0; i < b.length; ++i) {
            sb.append("0123456789abcdef".charAt(b[i] >>> 4 & 15));
            sb.append("0123456789abcdef".charAt(b[i] & 15));
        }

        return sb.toString();
    }

    /**
     * md5加密
     *
     * @param data 待加密的字符串
     * @return 加密后的字节数组
     */
    private static byte[] md5Hex(String data) {
        try {
            return MessageDigest.getInstance("MD5").digest(data.getBytes());
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}
